﻿using Microsoft.Extensions.DependencyInjection;
using RxxApi.Common.Helper;
using Serilog;
using Serilog.Configuration;
using Serilog.Core;
using Serilog.Events;
using Serilog.Formatting.Json;

namespace RxxApi.Extensions.ServiceExtensions;

public static class SerilogSetup
{
    /// <summary>
    /// 配置日志
    /// </summary>
    /// <param name="services"></param>
    /// <exception cref="ArgumentNullException"></exception>
    public static void AddSerilogSetup(this IServiceCollection services)
    {
        if (services == null) throw new ArgumentNullException(nameof(services));
        
            Log.Logger = new LoggerConfiguration().MinimumLevel.Debug()
             .Enrich.WithMachineName()
             .Enrich.WithEnvironmentUserName()
                 //.Enrich.WithEnvironmentName()
                 .Enrich.FromLogContext()
                 .Enrich.WithInfo()//使用自定义的Enricher
                                   //.Filter.ByIncludingOnly(Matching.WithProperty<string>("Hello", p => p.Equals("Hello World")))
                                   //.Filter.ByExcluding(Matching.WithProperty<string>("Hello", p => p.Equals("Hello World")))
                 .WriteTo.Console(new JsonFormatter())
                 //.WriteTo.File("logs/SerilFileLog.txt",
                 //    rollingInterval: RollingInterval.Day,
                 //    outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}]{Message:lj}{NewLine}{Exception}",
                 //    shared: true
                 //)
                 // 预定义的占位符可以非常丰富，包括但不限于：
                 //{ Timestamp}: 日志事件的时间戳。
                 //{ Level}: 日志事件的日志级别。
                 //{ Message}: 日志事件的消息。
                 //{ Exception}: 如果有异常对象与日志事件关联，则会包含该异常的堆栈跟踪。
                 //{ SourceContext}: 记录日志的源上下文，通常是记录器的名称。
                 //{ Properties}: 日志事件中的所有属性及其值。
                 //{ NewLine}: 换行符。
                 .WriteTo.Logger(x =>
                    x.Filter.ByIncludingOnly(e => e.Level == LogEventLevel.Information)
                    .WriteTo.File("Logs/Information.txt",
                    outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] {Message:lj}{Exception}{SourceContext}{NewLine}{Properties}{NewLine}",
                    rollingInterval: RollingInterval.Day, shared: true)
                )
                  .WriteTo.Logger(x =>
                    x.Filter.ByIncludingOnly(e => e.Level == LogEventLevel.Error)
                    .WriteTo.File("Logs/Error.txt",
                    outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] {Message:lj}{Exception}{SourceContext}{NewLine}{Properties}{NewLine}",
                    rollingInterval: RollingInterval.Day, shared: true)
                )
                .WriteTo.Logger(x =>
                    x.Filter.ByIncludingOnly(e => e.Level != LogEventLevel.Information && e.Level != LogEventLevel.Error)
                    .WriteTo.File("Logs/api.txt",
                    outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] {Message:lj}{Exception}{SourceContext}{NewLine}{Properties}{NewLine}",
                    rollingInterval: RollingInterval.Day, shared: true)
                )
                .CreateLogger();
    }
    public static LoggerConfiguration WithInfo(this LoggerEnrichmentConfiguration enrich)
    {
        if (enrich == null)
            throw new ArgumentNullException(nameof(enrich));

        return enrich.With<InfoEnricher>();
    }
    public class InfoEnricher : ILogEventEnricher
    {
        public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
        {
            //logEvent.AddPropertyIfAbsent(propertyFactory.CreateProperty("Hello", "Hello World"));
            logEvent.AddPropertyIfAbsent(propertyFactory.CreateProperty("SourceIp", GetLocalIpAddress.GeIpAddress()));
        }
    }
}
